package com.gfl.trivialrestclient.controllers.validators;

import java.util.regex.Pattern;

import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

import com.gfl.trivialrestclient.controllers.forms.UserCmd;
import com.gfl.trivialrestclient.services.UserService;


public class UserCmdValidator implements Validator {

	private final int MIN_PASSWORD_LENGTH = 5;
	private final static Pattern EMAIL_PATTERN = Pattern
			.compile(".+@.+\\.[a-z]+");
	private final static Pattern LOGIN_PATTERN = Pattern
			.compile("^[a-zA-Z\\d_]+$");

	private UserService userService;

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return UserCmd.class.equals(clazz);
	}

	@Override
	public void validate(Object target, Errors e) {
		ValidationUtils.rejectIfEmpty(e, "login", "login.empty", "Empty login");
		ValidationUtils.rejectIfEmpty(e, "password", "password.empty",
				"Empty password");
		ValidationUtils.rejectIfEmpty(e, "confirmPassword",
				"confirmPassword.empty", "Empty confirm password");
		ValidationUtils.rejectIfEmpty(e, "email", "email.empty", "Empty email");

		UserCmd userCmd = (UserCmd) target;

		// passwords
		if (userCmd.getPassword() != null) {
			// min length
			if (userCmd.getPassword().length() < MIN_PASSWORD_LENGTH) {
				e.rejectValue("password", "password.tosmall",
						"Password are to small");
			}
			// confirm match
			if (userCmd.getConfirmPassword() != null) {
				if (!userCmd.getPassword().equals(userCmd.getConfirmPassword())) {
					e.rejectValue("confirmPassword", "password.notmatch",
							"Passwords not match");
				}
			}
		}

		// email
		if (userCmd.getEmail() != null) {
			if (!isEmailValid(userCmd.getEmail())) {
				e.rejectValue("email", "email.wrong", "Wrong email format");
			}
		}

		// login
		if (userCmd.getLogin() != null) {
			if (!isLoginValid(userCmd.getLogin())) {
				e.rejectValue("login", "login.invalidchars",
						"Only alphanumeric chars are alloweds");
			} else {
				// check availability
				if (!userService.isUsernameAvailable(userCmd.getLogin())) {
					e.rejectValue("login", "login.notavailable",
							"Login already taken");
				}
			}

		}
	}

	private boolean isEmailValid(String email) {
		if (email == null) {
			return false;
		}

		return EMAIL_PATTERN.matcher(email).matches();
	}

	private boolean isLoginValid(String login) {
		if (login == null) {
			return false;
		}

		return LOGIN_PATTERN.matcher(login).matches();
	}
}
